#ifndef STRAY_BIND_H
#define STRAY_BIND_H

#include <boost/bind.hpp>

#include "Delegate.h"

#define STRAY_BIND_TEMPLATE_PARAM_0 typename Function
#define STRAY_BIND_TEMPLATE_PARAM_1 STRAY_BIND_TEMPLATE_PARAM_0, typename T1
#define STRAY_BIND_TEMPLATE_PARAM_2 STRAY_BIND_TEMPLATE_PARAM_1, typename T2
#define STRAY_BIND_TEMPLATE_PARAM_3 STRAY_BIND_TEMPLATE_PARAM_2, typename T3
#define STRAY_BIND_TEMPLATE_PARAM_4 STRAY_BIND_TEMPLATE_PARAM_3, typename T4
#define STRAY_BIND_TEMPLATE_PARAM_5 STRAY_BIND_TEMPLATE_PARAM_4, typename T5
#define STRAY_BIND_TEMPLATE_PARAM_6 STRAY_BIND_TEMPLATE_PARAM_5, typename T6
#define STRAY_BIND_TEMPLATE_PARAM_7 STRAY_BIND_TEMPLATE_PARAM_6, typename T7
#define STRAY_BIND_TEMPLATE_PARAM_8 STRAY_BIND_TEMPLATE_PARAM_7, typename T8

#define STRAY_BIND_ARG_DECL_0 Function f
#define STRAY_BIND_ARG_DECL_1 STRAY_BIND_ARG_DECL_0, T1 t1
#define STRAY_BIND_ARG_DECL_2 STRAY_BIND_ARG_DECL_1, T2 t2
#define STRAY_BIND_ARG_DECL_3 STRAY_BIND_ARG_DECL_2, T3 t3
#define STRAY_BIND_ARG_DECL_4 STRAY_BIND_ARG_DECL_3, T4 t4
#define STRAY_BIND_ARG_DECL_5 STRAY_BIND_ARG_DECL_4, T5 t5
#define STRAY_BIND_ARG_DECL_6 STRAY_BIND_ARG_DECL_5, T6 t6
#define STRAY_BIND_ARG_DECL_7 STRAY_BIND_ARG_DECL_6, T7 t7
#define STRAY_BIND_ARG_DECL_8 STRAY_BIND_ARG_DECL_7, T8 t8

#define STRAY_BIND_ARG_0 f
#define STRAY_BIND_ARG_1 STRAY_BIND_ARG_0, t1
#define STRAY_BIND_ARG_2 STRAY_BIND_ARG_1, t2
#define STRAY_BIND_ARG_3 STRAY_BIND_ARG_2, t3
#define STRAY_BIND_ARG_4 STRAY_BIND_ARG_3, t4
#define STRAY_BIND_ARG_5 STRAY_BIND_ARG_4, t5
#define STRAY_BIND_ARG_6 STRAY_BIND_ARG_5, t6
#define STRAY_BIND_ARG_7 STRAY_BIND_ARG_6, t7
#define STRAY_BIND_ARG_8 STRAY_BIND_ARG_7, t8

#define STRAY_BIND_TEMPLATE_FUNCTION_N(count) \
	template<STRAY_BIND_TEMPLATE_PARAM_##count> \
	BindObject bind(STRAY_BIND_ARG_DECL_##count) \
	{ \
		return boost::bind(STRAY_BIND_ARG_##count); \
	}

namespace Stray {

typedef Delegate<void (void)>::type BindObject;

STRAY_BIND_TEMPLATE_FUNCTION_N(0)
STRAY_BIND_TEMPLATE_FUNCTION_N(1)
STRAY_BIND_TEMPLATE_FUNCTION_N(2)
STRAY_BIND_TEMPLATE_FUNCTION_N(3)
STRAY_BIND_TEMPLATE_FUNCTION_N(4)
STRAY_BIND_TEMPLATE_FUNCTION_N(5)
STRAY_BIND_TEMPLATE_FUNCTION_N(6)
STRAY_BIND_TEMPLATE_FUNCTION_N(7)
STRAY_BIND_TEMPLATE_FUNCTION_N(8)

}

#endif